﻿using System;
using System.Collections.Generic;

namespace Aeon.Framework
{

/// <summary>
/// Context sensitive input wrapper class.
/// 
/// </summary>
public sealed class InputContext
    {
    // --- Inner:

    public delegate void InputFunction(ref object dto);     // Complex delegate for parameterized event/action pairs.
    public delegate void InputAction();                     // Simple delegate for event/action pairs.

    // --- Attributes:

    private String name;                                    // Identifier for screen state context.    
    private Dictionary<String,List<Object>> handlers;       // Pairs of Event notification label and action delegates.
                                                            // Action delegates can be:
                                                            // - List<Object> with a InputAction,
                                                            // - List<Object> with a InputFunction, and a parameter ref object array.

    // --- Properties:

    public string Name { get { return(name); } }

    // --- Constructor:
    
    public InputContext(String identifier)
        {
        name = identifier;

        handlers = new Dictionary<String,List<Object>>();
        }
    
    // --- Public Methods:

    /// <summary>
    /// Notifies the hook for that event, and executes relevant action, if any.
    /// 
    /// </summary>    
    public void Notify(String input)
        {
        List<Object> list;

        if (handlers.TryGetValue(input, out list))
            {
            if (list[0] is InputAction) { (list[0] as InputAction).Invoke(); }
            else {
                 InputFunction func = list[0] as InputFunction;
                 Object param = list[1];

                 func.Invoke(ref param);
                 }
            }
        }

    /// <summary>
    /// Adds a new input hook for an event/action pair.
    /// Simple hook.
    /// 
    /// </summary>
    public bool InsertHook(String input, InputAction action)
        {
        if (handlers.ContainsKey(input)) return(false);
        else {
             List<Object> lst = new List<Object>();
             lst.Add(action);

             handlers.Add(input,lst);
             return(true);
             }
        }

    /// <summary>
    /// Adds a new input hook for an event/action pair.
    /// Complex hook with pre-passed variable parameters.
    /// 
    /// </summary>
    public bool InsertHook(String input, InputFunction function, ref object dto)
        {
        if (handlers.ContainsKey(input)) return(false);
        else {
             List<Object> lst = new List<Object>();
             lst.Add(function);
             lst.Add(dto);

             handlers.Add(input,lst);
             return(true);
             }
        }

    /// <summary>
    /// Removes existent input hooks.
    /// Clears one event/action pair.
    /// 
    /// </summary>
    public bool RemoveHook(String input)
        {

        return(handlers.Remove(input));
        }

    /// <summary>
    /// Removes existent input hooks.
    /// Clears all events.
    /// 
    /// </summary>
    public bool RemoveHook()
        {
        handlers = new Dictionary<String,List<Object>>();
        return(true);
        }
        
    }


}